#ifndef GY_OBJECTGROUP_H
#define GY_OBJECTGROUP_H

#include <QObject>
#include <QGraphicsItem>
#include "Graphics/ContainerGraphics/GY_ContainerTransform.h"
#include "GY_ControlLibrary_global.h"
#include "Graphics/FormulaTransformation/GY_TransformationClass.h"

class GY_CalculationClass;

struct BindingInformation
{
    int type;//类型，1子类属性，0组件属性
    QVector<QVariant> value;//计算结果
    QVector<QString> source;//数学表达式
    QString pointName;//源名字
    QVector<QString> purpose;//目的名字
    PropertyType varType;//变量类型
};
Q_DECLARE_METATYPE(BindingInformation);

class GY_CONTROLLIBRARY_EXPORT GY_ObjectGroup : public GY_ContainerTransform
{
    Q_OBJECT
public:
    explicit Q_INVOKABLE GY_ObjectGroup(const QString &guid,QGraphicsItem *parent = nullptr);
    ~GY_ObjectGroup();
    /**
     * @brief addNewAttribute 增加自定义属性
     * @param name 属性名称
     * @param value 属性值
     * @return 是否增加成功
     */
    bool addAttribute(const QString &name, const QVariant &value);
    /**
     * @brief addNewAttribute 删除自定义属性
     * @param name 属性名称
     * @return 是否删除成功
     */
    bool deleteAttribute(const QString &name);
    /**
     * @brief changeAttribute 修改自定义属性
     * @param name 属性名称
     * @param value 属性值
     * @return 是否修改成功
     */
    QString changeAttribute(const QString &name, const QVariant &value);
    /**
     * @brief dataFlowEditor 数据绑定
     * @param source 源
     * @param purpose 目的
     * @param copy 为零正常储存信息,其余不储存该次绑定信息
     * @return 是否绑定成功
     */
    QString dataFlowEditor(QString &source, const QString &purpose, int copy=0);
    /**
     * @brief removeDataBinding 删除数据绑定
     * @param purpose 目的
     * @return 是否删除成功
     */
    QString removeDataBinding(const QString &purpose);
    /**
     * @brief removeAllItem 子类item全部移除
     */
    void removeAllItem();
    /**
     * @brief addAllItem 子类item全部添加
     */
    void addAllItem();
    /**
     * @brief setGloabalVariable 存放相关数据到绑定信息结构体
     * @param source 源表达式
     * @param name 变量名
     * @param pointName 未修改变量名
     * @param purpose 目的表达式
     */
    void setGloabalVariable(const QString &source,const QVector<QString> &name,const QVector<QString> &pointName,const QString &purpose);
    //!继承基类重写
    GY_Object * copyItem(const QString &guid = QString()) override;
    /**
     * @brief getNewAttribute 获取新增属性
     * @return 返回新增属性
     */
    QVector<QString> getNewAttribute();

private:
    /**
     * @brief initializationPropertyInfo 初始化属性信息
     */
    void initializationPropertyInfo();
    /**
     * @brief updatePosition 更新位置
     * @param name 属性名称
     * @param value 位置
     * @return 是否更新成功
     */
    bool updatePosition(const QString &name, const QVariant &value);
    /**
     * @brief updateAttribute 更新自定义属性
     * @param name 属性名称
     * @param value 自定义属性
     * @return 是否更新成功
     */
    bool updateAttribute(const QString &name, const QVariant &value);
    /**
     * @brief getType 获取数据类型
     * @param value 数据值
     * @return
     */
    PropertyType getType(const QVariant& value);
    /**
     * @brief checkProName 判断属性名称是否存在且合理
     * @param list 属性名称
     * @return 判断结果
     */
    bool checkProName(const QStringList& list);
    /**
     * @brief getProObject 获取对象指针
     * @param name 变量名称
     * @param obj 空指针
     * @param childrensMap map容器
     * @return 对象指针
     */
    GY_Object* getProObject(const QString& name, GY_Object* obj, QMap<QString,GY_Object*> childrensMap);
    /**
     * @brief getSourceType 获取源变量属性类型
     * @param sourceObjName item名称
     * @param sourceProperty 属性名称
     * @param name 变量名称
     * @param childrensMap map容器
     * @return 属性类型
     */
    PropertyType getSourceType(const QString& sourceObjName, const QString& sourceProperty, const QString& name, QMap<QString,GY_Object*> childrensMap);
    /**
     * @brief getQVariantType 根据PropertyType返回相对应QVariant初始值
     * @param type 属性类型
     * @return QVariant初始值
     */
    QVariant getQVariantType(const PropertyType& type);
    /**
     * @brief checkType 检查绑定属性类型是否一致
     * @param type 属性类型
     * @param property 属性名称
     * @param childrensMap map容器
     * @return 判断结果
     */
    bool checkType(const PropertyType& type, const QVector<QString>& property, QMap<QString,GY_Object*> childrensMap);
    /**
     * @brief typeMatching 判断类型是否匹配
     * @param purType 目的属性类型
     * @param proType 变量属性类型
     * @return 判断结果
     */
    bool typeMatching(const PropertyType& purType, PropertyType& proType);
    /**
     * @brief isPureNumber 是否为纯数字
     * @param str 字符串
     * @return 判断结果
     */
    bool isPureNumber(const QString& str);
    /**
     * @brief isSameProperty 属性是否相同
     * @param purpose 目的
     * @param source 源
     * @return 判断结果
     */
    bool isSameProperty(const QString& purpose, const QString& source);

private:
    /**
     * @brief m_pTransformationClass 公式转换类
     */
    GY_TransformationClass *m_pTransformationClass;
    /**
     * @brief m_pCalculationClass 计算类
     */
    GY_CalculationClass *m_pCalculationClass;
    /**
     * @brief m_ExecutionInformation 错误信息
     */
    QString m_ExecutionInformation = "OK";
    /**
     * @brief m_source 暂存源表达式
     */
    QString m_source;
    /**
     * @brief m_purpose 暂存目的表达式
     */
    QString m_purpose;
    /**
     * @brief m_bindInformationMap 所有表达式信息
     */
    QMap<QString,QVector<QString>> m_bindInformationMap;
    /**
     * @brief m_bindVec 组件新增属性
     */
    QVector<QString> m_bindVec;

private:
    /**
     * @brief m_biMap 存放绑定相关信息
     */
    QMap<QString,BindingInformation> m_biMap;
    /**
     * @brief m_attributeMap 存放新增属性信息
     */
    QMap<QString,QVariant> m_attributeMap;

signals:
    /**
     * @brief executionInformationSig 数学表达式有错信号
     * @param executionInformation 错误信息
     */
    void executionInformationSig(QString& executionInformation);

public slots:
    /**
     * @brief getExecutionInformation 数学表达式有错信号接收
     * @param executionInformation 错误信息
     */
    void getExecutionInformation(QString& executionInformation);

};

#endif // GY_OBJECTGROUP_H
